import { isArraylike, css } from './tools'
import { Callbacks } from './async/callback'
import { support } from './support'
import { attr, prop, addClass } from './dom/attribute'
import { toggle } from './dom/css'
import { serialize, ajax, load } from './ajax'
import { animate, slideUp, slideDown, slideToggle } from './animate'


function isHTMLElement(value:any): value is HTMLElement {
  return 'nodeType' in value
}


function jQuery(selector:string|HTMLElement|Function) {
  return new jQuery.fn.init(selector)
}

jQuery.fn = jQuery.prototype

jQuery.prototype.init = function(selector:string|HTMLElement|Function) {
  if(!selector || selector == null) return this

  if(typeof selector === 'string') {
    if(/^<([0-9a-z]+)>([\s\S]*<\/\1>)?$/.test(selector)) {
      
    } else {
      const nodeList = document.querySelectorAll(selector)
      for(let i = 0; i < nodeList.length; i++) {
        this[i] = nodeList[i]
      }
      this.length = nodeList.length
    }
  } else if(isHTMLElement(selector)) {
    
  } else {
    this.ready(selector)
  }
}

Object.assign(jQuery.prototype, {
  length: 0,

  css() {},
  html() {},
  find() {},
  ready() {},
  toArray() { return Array.prototype.slice.call(this) },
  get(index?:number) {},
  each() {},
  eq(index:number) {},
  first() {},
  last() {},
  pushStack() {},
  end() {},
  click() {},
  off() {},
  width() {},
  attr,
  prop,
  addClass,
  toggle,
  serialize,
  load,

})


jQuery.prototype.init.prototype = jQuery.prototype


jQuery.type = (value:unknown) => {
  return Object.prototype.toString.call(value)
    .replace(/^\[object (\w+)\]$/, '$1').toLowerCase()
}

jQuery.merge = () => {}
jQuery.parseHTML = (htmlStr:string) => {}
jQuery.parseJSON = (value:string) => JSON.parse(value)

jQuery.parseXML = (xml:string) => {
  const parser = new DOMParser()
  const doc = parser.parseFromString(xml, 'text/xml')

  if(!doc || doc.getElementsByTagName('parsererror').length) {
    throw new Error('parse error')
  }

  return doc
}

jQuery.isPlainObject = (value:unknown) => jQuery.type(value) === 'object'
jQuery.isFunction = (value:unknown) => typeof value === 'function'
jQuery.isArray = (value:unknown) => Array.isArray(value)
jQuery.makeArray = (value:Iterable<unknown>|ArrayLike<unknown>) => Array.prototype.slice.call(value)
jQuery.each = () => {}
jQuery.map = () => {}
jQuery.isReady = () => document.readyState !== 'loading'
jQuery.isWindow = (value:unknown) => value != null && value === (value as any).window
jQuery.isNumber = (value:unknown) => !isNaN(parseFloat(value as string)) && isFinite(value as number)

jQuery.isEmptyObject = (value:unknown) => {
  for(const key in value as object) {
    return false
  }
  return true
}

jQuery.noop = function() {}

jQuery.globalEval = (code:string) => {
  code = code.trim()

  if(/^(["'])use\s+strict\1/.test(code)) {
    const script = document.createElement('script')
    script.text = code
    document.head.appendChild(script).parentNode?.removeChild(script)
  } else {
    window.eval(code)
  }
}

jQuery.camelCase = () => {}

jQuery.nodeName = (elem:HTMLElement, name:string) => {
  return elem.nodeName && elem.nodeName === name.toUpperCase()
}

jQuery.trim = () => {}
jQuery.grep = () => {}

jQuery.inArray = (value:unknown, arr:unknown[], start:number=0) => {
  return Array.prototype.indexOf.call(arr, value as string, start)
}

jQuery.proxy = (fn:Function, thisArg:unknown, ...args:unknown[]) => {}
jQuery.access = () => {}
jQuery.now = ()=>new Date().toLocaleString()
jQuery.Callbacks = Callbacks
jQuery.support = support
jQuery.css = css
jQuery.ajax = ajax



function extend(plugin:object):void
function extend(target:object, ...source:object[]):void 
function extend(deep:boolean, target:object, ...source:object[]):void
function extend(...args:unknown[]) {
  if(args.length === 1) {

  }
}


jQuery.extend = jQuery.fn.extend = extend


window.$ = window.jQuery = jQuery
